/*
输入样例数量T，每组点的数量N，A组各点的坐标，B组各点的坐标
输入样例：
2
4
0 0 0 1 1 0 1 1
2 2 2 3 3 2 3 3
4
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

输出样例：
1.414
0.000
*/
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 200005

// 点结构
struct Point
{
    // 坐标
    double x,y;
    
    // 标记所属集合
    char flag;
} p[MAXN], p1[MAXN];

// 用于按x递增排序
int cmpx(Point a, Point b)
{
    return a.x < b.x;
}

// 用于按y递增排序
int cmpy(Point a,Point b)
{
    return a.y < b.y;
}

// 求两个点之间的距离
double dis(Point a, Point b)
{
    // 不同组的点之间求距离
    if(a.flag != b.flag)
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    
    // 同组中点之间距离为INF
    return INF;
}

// 求p[l..r]中不同组点之间的最小距离
double mindistance(int l,int r)
{
    // 区间中只有一个点
    if(l >= r)
        return INF;
    
    // 区间中只有两个点
    if(l+1 == r)
        return dis(p[l], p[r]);
    
    // 求中点位置
    int mid=(l+r)/2;	
    
    // 左半部分的最小距离
    double d1 = mindistance(l, mid);
    
    // 右半部分的最小距离
    double d2 = mindistance(mid+1, r);
    
    // 候选的最小距离
    double d=min(d1, d2);
    int cnt=0;
    
    // 与中点x方向距离<d的点存放在p1中
    for(int i=l; i<=r; i++)
        if(fabs(p[i].x-p[mid].x) < d)
            p1[cnt++] = p[i];
        
    // p1中所有点按y递增排序
    sort(p1, p1+cnt, cmpy);
    
    // 找出最近点距离
    for(int i=0; i<cnt; i++)
        for(int j=i+1,k=0; k<7 && j<cnt && p1[j].y-p1[i].y<d; j++,k++)
            d = min(d, dis(p1[i],p1[j]));
    return d;
}

int main()
{
    int t, n;
    
    // 测试用例数量
    scanf("%d", &t);
    
    while(t--)
    {
        // 坐标点个数
        scanf("%d", &n);
        
        //输入A集合的点
        for(int i=0; i<n; i++)
            scanf("%lf%lf", &p[i].x, &p[i].y), p[i].flag='A';
        
        // 输入B集合的点
        for(int i=n; i<2*n; i++)	
            scanf("%lf%lf", &p[i].x, &p[i].y), p[i].flag='B';
        
        // 全部点按x递增排序
        sort(p, p+2*n, cmpx);
        
        // 找两组点之间的最近点
        printf("%.3f\n", mindistance(0, 2*n-1));
    }
    return 0;
}

